作者:路人 | 来源:互联网 | 2022-12-15 12:34
考虑这个测试
import shutil, tempfile
from os import path
import unittest
from pathlib import Path
class TestExample(unittest.TestCase):
def setUp(self):
# Create a temporary directory
self.test_dir = tempfile.TemporaryDirectory()
self.test_dir2 = tempfile.mkdtemp()
def tearDown(self):
# Remove the directory after the test
shutil.rmtree(self.test_dir2)
shutil.rmtree(self.test_dir.name) #throws error
def test_something(self):
self.assertTrue(Path(self.test_dir.name).is_dir())
self.assertTrue(Path(self.test_dir2).is_dir())
if __name__ == '__main__':
unittest.main()
在tearDown
但引发错误
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpxz7ts7a7'
指的是self.test_dir.name
.
根据源代码tempfile
,两个元素是相同的.
def __init__(self, suffix=None, prefix=None, dir=None):
self.name = mkdtemp(suffix, prefix, dir)
self._finalizer = _weakref.finalize(
self, self._cleanup, self.name,
warn_message="Implicitly cleaning up {!r}".format(self))
而且我没有在上下文中使用它,所以__exit__()
不应该根据我的理解调用它.
怎么了?
1> wim..:
不要用它来清理这些shutil
.本tempfile.TemporaryDirectory
类提供了一个cleanup()
方法,只需调用,如果你想选择加入一个明确的清理.
你的代码崩溃的原因是TemporaryDirectory
该类被设计为一旦超出范围(ref count为零)就自行清理.但是,由于您已经手动从文件系统中删除了该目录,因此当实例随后尝试删除自身时,拆除将失败."没有这样的文件或目录"错误来自于TemporaryDirectory
它自己的拆除,它不是来自你的shutil.rmtree
线路!
2> Jean-Françoi..:
它与上下文无关:
import tempfile,os
t = tempfile.TemporaryDirectory()
s = t.name
print(os.path.isdir(s))
# os.rmdir(s) called here triggers error on the next line
t = None
print(os.path.isdir(s))
它打印
True
False
因此,一旦t
设置为None
对象的引用被垃圾收集并且目录被删除,正如文档所述:
完成上下文或销毁临时目录对象后,将从文件系统中删除新创建的临时目录及其所有内容.
os.rmdir(s)
在下面的代码片段中取消注释会在对象完成时抛出异常:
Exception ignored in:
Traceback (most recent call last):
File "L:\Python34\lib\weakref.py", line 519, in __call__
return info.func(*info.args, **(info.kwargs or {}))
File "L:\Python34\lib\tempfile.py", line 698, in _cleanup
_shutil.rmtree(name)
File "L:\Python34\lib\shutil.py", line 482, in rmtree
return _rmtree_unsafe(path, onerror)
File "L:\Python34\lib\shutil.py", line 364, in _rmtree_unsafe
onerror(os.listdir, path, sys.exc_info())
File "L:\Python34\lib\shutil.py", line 362, in _rmtree_unsafe
names = os.listdir(path)
所以你的调用可能会成功,但你在对象的最终确定中得到了异常(之后)
调用cleanup()
对象方法而不是rmtree
解决问题,因为更新了对象内部状态,以便在最终确定时不尝试删除目录(如果你问我,对象应该在尝试清理之前测试目录是否存在,但即便如此因为它不是原子操作所以总是有效
所以更换
shutil.rmtree(self.test_dir.name)
通过
self.test_dir.cleanup()
或者什么都不做,让对象在删除时清理目录.